package com.wss.lsl.lucene.demo;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import com.webssky.jcseg.core.JcsegTaskConfig;
import com.webssky.jcseg.lucene.JcsegAnalyzer4X;

public class TextFileIndexer {

	//private static Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);
	private IndexWriter writer;
	private List<File> queue = new ArrayList<File>();
	private static JcsegAnalyzer4X analyzer = new JcsegAnalyzer4X(JcsegTaskConfig.COMPLEX_MODE);
	
	static{
		JcsegTaskConfig config = analyzer.getTaskConfig();
		//追加同义词到分词结果中, 需要在 jcseg.properties 中配置 jcseg.loadsyn=1
		//追加拼音到分词结果中, 需要在 jcseg.properties 中配置 jcseg.loadpinyin=1
		config.setAppendCJKSyn(true); 
		config.setAppendCJKPinyin(true);
	}

	public static void main(String[] args) throws IOException {
		
		System.out.println("中文输出测试!");
		System.out
				.println("Enter the path where the index will be created:(e.g. /tmp/index or c:\\index )");
		String indexLocation = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
		String s = br.readLine();
		TextFileIndexer fileIndexer = null;
		try {
			indexLocation = s;
			fileIndexer = new TextFileIndexer(indexLocation);
		} catch (Exception e) {
			System.out.println("Cannot create index..." + e.getMessage());
			System.exit(-1);
		}

		while (true) {
			System.out
					.println("Enter the full path to add into the index (q=quit): (e.g. /home/ron/mydir or c:\\Users\\ron\\mydir)");
			System.out
					.println("[Acceptable file types: .xml, .html, .html, .txt]");
			s = br.readLine();
			if (s.equalsIgnoreCase("q")) {
				break;
			}
			fileIndexer.indexFileOrDirectory(s);
		}
		fileIndexer.closeIndexer();

		IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(
				indexLocation)));
		IndexSearcher searcher = new IndexSearcher(reader);
		s = "";
		while (true) {
			try {
				System.out.println("Enter the search query(q=quit):");
				s = br.readLine();
				if (s.equalsIgnoreCase("q")) {
					break;
				}
				Query query = new QueryParser(Version.LUCENE_44, "contents",
						analyzer).parse(s);
				// 标准输入，在控制台显示中文乱码问题。以上语句能解析中文 
				System.out.println("query: " + new String(s.getBytes()));
				ScoreDoc[] hits = searcher.search(query, 10).scoreDocs;
				int i = 1;
				System.out.println("Found " + hits.length + " hits.");
				for (ScoreDoc hit : hits) {
					Document doc = searcher.doc(hit.doc);
					System.out.println((i++) + ". filename: "
							+ doc.get("filename") + "\tpath: "
							+ doc.get("path") + "\tcontents: "
							+ doc.get("contents") + "\t score:" + hit.doc);
				}
			} catch (Exception e) {
				e.printStackTrace();
				System.out.println("Error searching " + s + ": " +  e.getMessage());
			}
		}
		br.close();
	}

	public void indexFileOrDirectory(String fileName) throws IOException {

		addFile(new File(fileName));
		int originalNumDocs = writer.numDocs();
		for (File file : queue) {
			try {
				// 正确读取中文文件，跟文件的编码有关
				BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));
				Document doc = new Document();
				doc.add(new TextField("contents", br));
				doc.add(new StringField("path", file.getAbsolutePath(),
						Field.Store.YES));
				doc.add(new StringField("filename", file.getName(),
						Field.Store.YES));
				writer.addDocument(doc);
				writer.commit();
				System.out.println("Added " + file);
				br.close();
			} catch (Exception e) {
				System.out.println("Could not add " + file);
			} 
		}

		int newNumDocs = writer.numDocs();
		System.out.println("");
		System.out.println("*************************");
		System.out
				.println("Added " + (newNumDocs - originalNumDocs) + " hits.");
		System.out.println("*************************");
		queue.clear();
	}

	private void addFile(File file) {
		if (!file.exists()) {
			System.out.println("File not found!");
		} else if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (File f : files) {
				addFile(f);
			}
		} else {
			String fileName = file.getName().toLowerCase();
			if (fileName.endsWith(".htm") || fileName.endsWith(".html")
					|| fileName.endsWith(".xml") || fileName.endsWith(".txt")) {
				queue.add(file);
			} else {
				System.out.println("Skip file: " + fileName);
			}
		}
	}

	public TextFileIndexer(String indexLocation) throws IOException {

		Directory directory = FSDirectory.open(new File(indexLocation));
		IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_44,
				analyzer);
		writer = new IndexWriter(directory, config);
		writer.deleteAll();
	}

	public void closeIndexer() throws IOException {
		writer.close();
	}
}
